package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.common.PageResult;
import com.itheima.dto.DishDto;
import com.itheima.dto.SetmealDto;
import com.itheima.entity.Category;
import com.itheima.entity.Dish;
import com.itheima.entity.Setmeal;
import com.itheima.entity.SetmealDish;
import com.itheima.exception.BusinessException;
import com.itheima.mapper.SetmealMapper;
import com.itheima.service.CategoryService;
import com.itheima.service.SetmealDishService;
import com.itheima.service.SetmealService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 套餐业务层实现类
 */
@Service
@Transactional
@Slf4j
public class SetmealServiceImpl implements SetmealService {

    @Autowired
    private SetmealMapper setmealMapper;

    @Autowired
    private SetmealDishService setmealDishService;

    @Autowired
    private CategoryService categoryService;

    /**
     * 新增套餐  套餐表 + 套餐菜品表
     *
     * @param setmealDto
     */
    @Override
    @CacheEvict(value = "setmeal",allEntries = true)
    public void save(SetmealDto setmealDto) {
        //1先根据套餐名称查询套餐表
        LambdaQueryWrapper<Setmeal> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dishLambdaQueryWrapper.eq(StringUtils.isNotEmpty(setmealDto.getName()), Setmeal::getName, setmealDto.getName());//套餐名称条件
        Integer count = setmealMapper.selectCount(dishLambdaQueryWrapper);
        if (count > 0) {
            //2套餐名称如果存在则抛出异常告知用户套餐已经存在
            throw new BusinessException("套餐[" + setmealDto.getName() + "]已经存在了");
        }
        //3套餐名称不存在，则保存套餐
        setmealMapper.insert(setmealDto);//保存套餐后setmealDto 就有套餐主键id
        //4循环遍历到套餐菜品表中
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        if (!CollectionUtils.isEmpty(setmealDishes)) {
            //方式二：
            //setmealDishes集合进行遍历
            setmealDishes.stream().map(
                    setmealDish -> {
                        //setmealDishe：集合中每一个对象
                        setmealDish.setSetmealId(setmealDto.getId());
                        setmealDishService.insert(setmealDish);
                        log.debug("**往setmealDish表保存数据成功了**");
                        return setmealDish;
                    }
            ).collect(Collectors.toList());
            //方式一：
            /*for (SetmealDish setmealDish : setmealDishes) {
                setmealDish.setSetmealId(setmealDto.getId());//Setmeal套餐表中主键id
                setmealDishService.insert(setmealDish);
            }*/
        }
        log.debug("**往setmeal表保存数据成功了**");
    }

    /**
     * 套餐分页查询
     *
     * @param page
     * @param pageSize
     * @param name
     */
    @Override
    public PageResult<SetmealDto> findPage(Long page, Long pageSize, String name) {
        // 2.1 new Page(page,pageSize)
        Page pp = new Page(page, pageSize);
        //2.1.1 添加name条件
        LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(StringUtils.isNotEmpty(name), Setmeal::getName, name);//用户名
        //2.2 selectPage 进行分页
        setmealMapper.selectPage(pp, lambdaQueryWrapper);
        //得到菜品分页集合数据
        List<Setmeal> records = pp.getRecords();
        //将List<Setmeal>集合转换为List<SetmealDto>
        List<SetmealDto> setmealDtoList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(records)) {
            setmealDtoList = records.stream().map(
                    item -> {
                        SetmealDto setmealDto = new SetmealDto();
                        //方式二： 例如：A对象复制到B对象中 A对象中的属性名称以及类型 跟 B对象中的属性名称以及类型 一样才行
                        BeanUtils.copyProperties(item, setmealDto);
                        Category category = categoryService.findById(item.getCategoryId());
                        setmealDto.setCategoryName(category.getName());//套餐分类名称
                        return setmealDto;
                    }
            ).collect(Collectors.toList());
        }
        pp.setRecords(setmealDtoList);//将转换后的 List<SetmealDto>设置Records属性上
        //2.3 将page对象中total records 封装到PageResult对象中
        log.debug("员工分页总记录数{}，当前页面数据{}", pp.getTotal(), pp.getRecords());
        return new PageResult<>(pp.getTotal(), pp.getRecords());
    }

    /**
     * 套餐删除
     *
     * @param ids
     */
    @Override
    @CacheEvict(value = "setmeal",allEntries = true)
    public void deleteByIds(List<Long> ids) {
        if (!CollectionUtils.isEmpty(ids)) {
            //1判断套餐是否在售
            for (Long setmealId : ids) {
                //setmealId套餐id
                LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                //条件 套餐id + 状态==1 （1：启售 0：停售）
                lambdaQueryWrapper.eq(Setmeal::getId, setmealId);
                lambdaQueryWrapper.eq(Setmeal::getStatus, 1);//套餐是否是启售状态 如果是不能删除
                Setmeal setmeal = setmealMapper.selectOne(lambdaQueryWrapper);
                //2如果在售 不能删除
                if (setmeal != null) {
                    throw new BusinessException("套餐[" + setmeal.getName() + "]启售中，不能删除");
                }
            }
            //3如果停售 则可以直接删除套餐
            setmealMapper.deleteBatchIds(ids);
            log.debug("**删除套餐数据成功了**");
            //4还需删除套餐菜品表关联数据
            setmealDishService.deleteBySetmealIds(ids);
            log.debug("**删除套餐菜品数据成功了**");
        }
    }

    /**
     * 查询套餐列表数据
     *
     * @param setmeal
     */
//    setmeal 可以理解为一个表名
    @Cacheable(value = "setmeal",key = "#setmeal.categoryId + '_' + #setmeal.status")
    @Override
    public List<Setmeal> list(Setmeal setmeal) {
        //1.构造查询条件
        LambdaQueryWrapper<Setmeal> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Setmeal::getCategoryId,setmeal.getCategoryId());//套餐分类id
        lambdaQueryWrapper.eq(Setmeal::getStatus,setmeal.getStatus());//页面传入1（状态正常的套餐）
        //2.根据条件查询setmeal套餐表数据

        return setmealMapper.selectList(lambdaQueryWrapper);
    }
}
